4.2 Obtaining an end-user based access token using PKCE
Once you have configured the web.oauth2 web service for PKCE, you can request your user-based authentication code, and use that to obtain an access token that you can use to call the API.
For more information on PKCE, including details of requirements for the code verifier and code challenge, see the Proof Key for Code Exchange by OAuth Public Clients RFC:
4.2.1 Generating a PKCE code verifier and code challenge
The PKCE code verifier and code challenge are used to request the authorization code.
-
Generate a cryptographically-random key.
This is the code verifier.
The code verifier must be a high-entropy cryptographic random string using the following characters:
[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
The minimum length is 43 characters, and the maximum length is 128 characters.
-
Generate a SHA-256 hash of this key, then encode it using Base64 URL encoding.
This is the code challenge.
Important: Base64 URL encoding is slightly different to standard Base64 encoding.
See the Protocol section of the PKCE standard for details of requirements for the code verifier and code challenge:
Example PowerShell script for generating a code challenge from a given code verifier:
$code_verifier ='TiGVEDHIRkdTpif4zLw8v6tcdG2VJ.vP4r0fuLhsXIj'
# Hash the code verifier using SHA-256
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create("sha256")
$hashOfSecret = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($code_verifier))
# Convert to Base64 URL encoded (slightly different to normal Base64)
$clientSecret = [System.Convert]::ToBase64String($hashOfSecret)
$clientSecret = $clientSecret.Split('=')[0]
$clientSecret = $clientSecret.Replace('+', '–')
$clientSecret = $clientSecret.Replace('/', '_')
# Output the results
Write-Output ("`r`nThe code verifier is: `r`n`r`n$code_verifier")
Write-Output ("`r`nAnd code challenge is:`r`n`r`n$clientSecret" )
# Wait for a keypress
Write-Host "`r`nPress any key to continue...`r`n" -ForegroundColor Yellow
[void][System.Console]::ReadKey($true)
4.2.2 Requesting an authorization code
You must use the PKCE code challenge to request an authorization code from the MyID authentication service, and provide your user credentials.
-
From your website, post the following information to the MyID authorization URL:
https://<server>/web.oauth2/connect/authorize
-
client_id – the ID of your system; for example:
myid.myclient
-
scope – set this to myid.rest.basic
-
redirect_uri – set this to the URL of the page on your website to which the authorization code will be returned. This must be the same as the URL you specified in the appsettings.Production.json file.
-
response_type – set this to code
-
code_challenge – set this to the code challenge you generated. This is the Base64 URL-encoded SHA-256 hash of the random code verifier you created.
-
code_challenge_method – set this to S256
When you post this request, the MyID authentication service prompts you for your user credentials. The available methods of authentication depend on how you have configured your system; the same methods are available for authentication as are available in the MyID Operator Client.
-
-
Complete the authentication using your method of choice; for example, security questions or smart card.
Note: You may need to ensure that the MyID Client Service is running on your PC.
-
Capture the code parameter that is returned to the page you specified in the redirect_uri parameter.
This is your authorization code, which can be used once to request an access token. You can use the access token repeatedly until it expires, but if you need to request another access token, you must first request another authorization code and go through the user authentication procedure again.
4.2.3 Requesting an access token
Once you have your authorization code, you can request an access token that allows you to call the API.
-
Post the following information to the MyID token URL:
https://<server>/web.oauth2/connect/token
-
grant_type – set this to authorization_code
-
client_id – the ID of your system; for example:
myid.myclient
-
code_verifier – set this to the code verifier you created.
Note: Do not use the Base64 URL-encoded SHA-256 hash (the code challenge) – use the original plaintext value. The server compares this value to the encoded hash you provided when you requested the authorization code.
-
code – set this to the authorization code you obtained from the server.
-
redirect_uri – set this to the URL of the page on your website to which the access token will be returned. This must be the same as the URL you specified when you requested the authorization code.
-
-
Capture the access_token that is returned.
You can now use this access token to call the API.
See section 5.1, Calling the API from an external system for more information on using an access token.
The request returns a block of JSON containing the following:
-
access_token – your access token.
-
expires_in – the lifetime in seconds for the token. Once the lifetime has expired, you must request a new access token.
-
token_type – always Bearer.
-
scope – the scope configured for the client in the web.oauth2 web service; usually myid.rest.basic.
For example:
{"access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjI4ckl2ZDdmMGUwPSIsInR5cCI6ImF0K2p3dCJ9.eyJuYmYiOjE2MTcwMjQ2NzYsImV4cCI6MTYxNzAyODI3NiwiaXNzIjoiaHR0cHM6Ly9yZWFjdC5kb21haW4zMS5sb2NhbC93ZWIub2F1dGgyIiwiYXVkIjoibXlpZC5yZXN0IiwiY2xpZW50X2lkIjoibXlpZC5teWNsaWVudCIsInN1YiI6IjVkM2VhYzg1LWZhNjQtNDg5MS1iOThhLTUyNDEyYjBjNTg1ZCIsImF1dGhfdGltZSI6MTYxNzAyNDY2MywiaWRwIjoibG9jYWwiLCJteWlkU2Vzc2lvbklkIjoiLTQzNjY2NTY5NCw3MkQ3RDJDRC1GNDQ0LTRFMkQtODlBQS05MEIxNDJBMEQxOTEiLCJqdGkiOiI0NDY2N0MwMUMyRURDNTU3OEM1NTBGMTU4NkMwMURBOSIsInNpZCI6IjMxOTNFMTMwOTQwODk2MEVGRjVBMDM0RjVBMTQxMzlDIiwiaWF0IjoxNjE3MDI0Njc2LCJzY29wZSI6WyJteWlkLnJlc3QuYmFzaWMiXSwiYW1yIjpbInB3ZCJdfQ.Xyfn_SXPOtzGCiDdhNrtCn0PtqOIJ8TPbLpUCmzKTY9ZG9azRQo_bF4bWCi0wQwNM31YJoNwR6OV4bxOTbzvIDdhqFeOr5U0SpLICecIKdKdknDyShwAV7wRELV4ggs-rMO31hIc-W6B4iVm3tpDvczNyN4MMAXE8490zLJbWIYmImaTwhIaJI_uLWu3SIZkBovlxV7_2PL7R5s4sK2hZL9px2jGAyPkQgaQ-k7_6DXNe2utmMO9L2QzXLsSU5RwDLBAU6n6aw_0RUEe4DuNwICy55Wvun9TrN55P2_39OL5MoOQo0D_ZUh8nSzvgSW4cZR_ax1ZzXDgew3XwcXJKQ","expires_in":3600,"token_type":"Bearer","scope":"myid.rest.basic"}